from rest_framework import serializers
from rest_framework.generics import RetrieveAPIView
from django.db.models import F
from django.db.models import Max
from django.forms import model_to_dict
from django.db import transaction
from api import models

class NewsOneModelSerializer(serializers.ModelSerializer):
    '''
    获取单条动态的序列化
    '''
    images=serializers.SerializerMethodField()
    user=serializers.SerializerMethodField()
    topic=serializers.SerializerMethodField()
    viewer = serializers.SerializerMethodField()
    create_date=serializers.DateTimeField(format='%Y-%m-%d %H:%M:%S')
    comment=serializers.SerializerMethodField()
    is_favor=serializers.SerializerMethodField()

    class Meta:
        model=models.News
        exclude=['cover',]

    def get_images(self,obj):
        image_set=models.NewsDetail.objects.filter(news=obj)
        return [model_to_dict(item,['key','cos_path']) for item in image_set]

    def get_user(self,obj):
        return model_to_dict(obj.user,['avatar','nickname'])

    def get_topic(self,obj):
        topic=obj.topic
        if topic:
            return model_to_dict(topic,['id','title'])
        else:
            return None

    def get_viewer(self,obj):
        viewer_set=models.ViewerRecord.objects.filter(news=obj).order_by('-id')
        result=[model_to_dict(row.user,['id','avatar']) for row in viewer_set[:10]]
        count=viewer_set.count()
        return {'count':count,'result':result}

    def get_comment(self,obj):
        first_id_set=models.CommentRecord.objects.filter(news=obj,depth=1).order_by('id').values_list('pk')[:10]
        second_id_set=models.CommentRecord.objects.filter(
            news=obj,depth=2,reply_id__in=first_id_set).values('reply_id').annotate(max_id=Max('id'))

        first_queryset=models.CommentRecord.objects.filter(
            news=obj,depth=1).order_by('id').values('id','content','user__nickname','create_date')[:10]
        second_queryset = models.CommentRecord.objects.filter(
            id__in=[item['max_id' ] for item in second_id_set]).values(
            'id','reply_id','content','user__nickname','create_date')
        first_dict={}
        for item in first_queryset:
            first_dict[item['id']]=item
            first_dict[item['id']]['child']=[]
        for item in second_queryset:
            first_dict[item['reply_id']]['child'].append(item)
        return first_dict.values()

    def get_is_favor(self,obj):
        user=self.context['request'].user
        if not user:
            return False
        exists=models.NewsFavorRecord.objects.filter(news=obj,user=user).exists()
        if exists:
            return True
        else:
            return False

class NewsRetrieveAPIView(RetrieveAPIView):
    serializer_class = NewsOneModelSerializer
    queryset = models.News.objects
    def get(self, request, *args, **kwargs):

        response=super().get(request, * args, ** kwargs)
        if not request.user:
            return response
        instance=self.get_object()

        exists=models.ViewerRecord.objects.filter(news=instance,user=request.user).exists()

        if  exists:
            return response
        else:
            with transaction.atomic():
                models.ViewerRecord.objects.create(news=instance,user=request.user)
                # models.News.objects.filter(pk=instance.pk).update(viewer_count=F('viewer_count')+1)
                models.News.objects.filter(pk=instance.pk).update(viewer_count=F('viewer_count') + 1)
                return response